package com.onix.scalecamerapreview.translate.msOcr;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.support.v7.graphics.Palette;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;

import com.github.chrisbanes.photoview.PhotoView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.onix.scalecamerapreview.MyApplication;
import com.onix.scalecamerapreview.translate.OCR.MsBitmapView;
import com.onix.scalecamerapreview.translate.RetrofitUtil;
import com.onix.scalecamerapreview.translate.Textbean;
import com.onix.scalecamerapreview.translate.TranslateResult;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import me.shaohui.advancedluban.Luban;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MsRecognition {
    public static String URL = "https://westus.api.cognitive.microsoft.com/vision/v2.0/ocr";
    Gson gson = null;
    boolean FLAG = true;
    private MsRecognition(){
        gson = new Gson();
    }
    public static class SingleClass{
        private final static MsRecognition sMsRecognition = new MsRecognition();
    }

    public static MsRecognition getInstance(){
        return SingleClass.sMsRecognition;
    }


    public void execute(Bitmap bmp){
        int bytes = bmp.getByteCount();
        ByteBuffer buf = ByteBuffer.allocate(bytes);
        bmp.copyPixelsToBuffer(buf);
        byte[] byteArray = buf.array();
        execute(byteArray,null);
    }

    public void execute(Uri uri){
        RxImageUtils.getBitmap(uri,600,600)
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bmp) throws Exception {
                        int bytes = bmp.getByteCount();
                        ByteBuffer buf = ByteBuffer.allocate(bytes);
                        bmp.copyPixelsToBuffer(buf);
                        byte[] byteArray = buf.array();
                        execute(byteArray,null);
                    }
                });
    }

    public void execute(String filePath){
        execute(File2byte(filePath),null);
    }

    public void execute(InputStream inStream, MsBitmapView msBitmapView){
        try {
            execute( input2byte(inStream),msBitmapView);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public  byte[] input2byte(InputStream inStream)
            throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }

    public static byte[] File2byte(String filePath)
    {
        byte[] buffer = null;
        try
        {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1)
            {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return buffer;
    }

    public Observable<File> compress(final CompressionRequest request){
        if (request.file == null || !request.file.exists()) {
            return Observable.error(new RuntimeException("File not found!"));
        }
        if (request.file.length() <= 200 * 1024) {
            return Observable.just(request.file);
        }
        return Observable.just(request.file)
                .flatMap(new Function<File, ObservableSource<File>>() {
                    @Override
                    public ObservableSource<File> apply(File file) throws Exception {
                        Log.e("AAA","压缩运行在什么线程" + Thread.currentThread().getName());
                        int[] imageSize = ImageUtils.getImageSize(file.getAbsolutePath());
                        String toJson = gson.toJson(imageSize);
                        Log.d("compress之前","size " +toJson);
                        Log.d("compress之前", String.format("executeUseCase %s ,size: %d", request.file.getAbsolutePath(), file.length()));
                        return Luban.compress(request.context, request.file)
                                .putGear(Luban.CUSTOM_GEAR)
                                .setCompressFormat(Bitmap.CompressFormat.JPEG)
                                .setMaxSize(request.maxSize)//1m 限制, 限制最终图片大小（单位：Kb）
                                .asObservable();
                    }
                });
    }

    public void execute(CompressionRequest request, final PhotoView msBitmapView, final String toLanguage){
        Log.e("AAA","execute运行在什么线程" + Thread.currentThread().getName());

        compress(request)
                .observeOn(Schedulers.io())
                .map(new Function<File, MSResultBean>() {
            @Override
            public MSResultBean apply(File file) throws Exception {
                Log.e("AAA","网络请求运行在什么线程" + Thread.currentThread().getName());
                int[] imageSize = ImageUtils.getImageSize(file.getAbsolutePath());
                String toJson = gson.toJson(imageSize);
                Log.d("compress之后","size " +toJson+ " 文件大小 "+file.length());
                RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"),file);
                Log.d("AAA",body.toString());
                MultipartBody.Builder multiBuilder=new MultipartBody.Builder();
                multiBuilder.addPart(body);
                multiBuilder.addFormDataPart("language","unk");
                multiBuilder.addFormDataPart("detectOrientation","true");
                RequestBody multiBody=multiBuilder.build();
                Request request = new Request.Builder()
                        .url(URL)
                        .post(multiBody)
                        .addHeader("Content-Type", "application/octet-stream")
                        .addHeader("Ocp-Apim-Subscription-Key", "de418b4320664b1598d05b39af0736c6")
                        .build();
                OkHttpClient httpClient = RetrofitUtil.getHttpClient();
                Response response = httpClient.newCall(request).execute();
                if(response.isSuccessful()){
                    String result = response.body().string();
                    Log.d("AAA",response.code()+"");
                    MSResultBean msResultBean = gson.fromJson(result, MSResultBean.class);
                    msResultBean.setFile(file);
                    return msResultBean;
                }else if(response.code() == 400 ||response.code() == 415 || response.code() == 500){
                    String result = response.body().string();
                    MsOrcException msOrcException = gson.fromJson(result, MsOrcException.class);
                    throw msOrcException;
                }
                return null;
            }
        }).map(new Function<MSResultBean, List<TranslateResult>>() {
            @Override
            public List<TranslateResult> apply(MSResultBean msResultBean) throws Exception {
                if(FLAG){
                    String a ="他的界面极简，";
                    String b ="基佬紫为主,";
                    String c ="图标样式采用流行的扁平化";
                    String d ="支持拍照翻译";
                    List<TranslateResult> translateResults = new ArrayList<>();
                    for (int i=0;i<4;i++){
                        String text ="";
                        if(i ==0){
                            text =a;
                        }else if(i ==1){
                            text =b;
                        }else if(i == 2){
                            text =c;
                        }else {
                            text = d;
                        }
                        TranslateResult translateResult= new TranslateResult();
                        if(i == 0){
                            translateResult.setFile(msResultBean.getFile());
                        }
                        ArrayList<TranslateResult.TranslationsBean> translationsBeans = new ArrayList<>();
                        TranslateResult.TranslationsBean translationsBean1 = new TranslateResult.TranslationsBean();
                        translationsBean1.setText(text);
                        translationsBeans.add(translationsBean1);
                        translateResult.setTranslations(translationsBeans);
                        translateResults.add(translateResult);
                    }
                    List<Line> lines = msResultBean.getRegions().get(0).getLines();
                    for (int i =0;i<translateResults.size();i++){
                        TranslateResult translateResult = translateResults.get(i);
                        if(i ==0){
                            translateResult.setFile(msResultBean.getFile());
                        }
                        TranslateResult.TranslationsBean translationsBean = translateResult.getTranslations().get(0);
                        String boundingBox = lines.get(i).getBoundingBox();
                        String[] split = boundingBox.split(",");
                        int left = Integer.valueOf(split[0]);
                        int top = Integer.valueOf(split[1]);
                        int right = left+Integer.valueOf(split[2]);
                        int bootom = top + Integer.valueOf(split[3]);
                        translationsBean.setRect(new Rect(left,top,right,bootom));
                    }

                    return translateResults;
                }


                Log.e("AAA","翻译网络请求运行在什么线程" + Thread.currentThread().getName());
                //获取语言
                String language = msResultBean.getLanguage();
                Log.d("AAA","language "+language);
                String url = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from="+language+"&to="+toLanguage;
                Log.d("AAA","翻译的url "+url);
                List<Line> lines = msResultBean.getRegions().get(0).getLines();
                List<Textbean> textbeans = new ArrayList<>();
                for (Line line : lines) {
                    StringBuilder stringBuilder = new StringBuilder();
                    List<Line.Word> words = line.getWords();
                    for (Line.Word word : words) {
                        stringBuilder.append(word.getText());
                    }
                    Textbean textbean = new Textbean();
                    textbean.Text = stringBuilder.toString();
                    textbeans.add(textbean);
                }
                String str=gson.toJson(textbeans);
                Log.d("AAA","str "+str);
                RequestBody body = RequestBody.create(MediaType.parse("application/json"),str);
                Request request = new Request.Builder()
                        .url(url)
                        .post(body)
                        .addHeader("Ocp-Apim-Subscription-Key", "de418b4320664b1598d05b39af0736c6")
                        .addHeader("Content-Type", "application/json")
                        .build();
                OkHttpClient httpClient = RetrofitUtil.getHttpClient();
                Response response = httpClient.newCall(request).execute();

                if(response.isSuccessful()){
                    String result = response.body().string();
                    List<TranslateResult> translateResults = gson.fromJson(result, new TypeToken<List<TranslateResult>>() {
                    }.getType());
                    for (int i =0;i<translateResults.size();i++){
                        TranslateResult translateResult = translateResults.get(i);
                        if(i ==0){
                            translateResult.setFile(msResultBean.getFile());
                        }
                        TranslateResult.TranslationsBean translationsBean = translateResult.getTranslations().get(0);
                        String boundingBox = lines.get(i).getBoundingBox();
                        String[] split = boundingBox.split(",");
                        int left = Integer.valueOf(split[0]);
                        int top = Integer.valueOf(split[1]);
                        int right = left+Integer.valueOf(split[2]);
                        int bootom = top + Integer.valueOf(split[3]);
                        translationsBean.setRect(new Rect(left,top,right,bootom));
                    }
                    return translateResults;
                }
                return null;
            }
        })
                .map(new Function< List<TranslateResult>, OcrResultBitmpa>() {
            @Override
            public OcrResultBitmpa apply( List<TranslateResult> translateResults) throws Exception {
                Log.e("AAA","转换bitmap请求运行在什么线程" + Thread.currentThread().getName());
                OcrResultBitmpa ocrResultBitmpa = new OcrResultBitmpa();
                byte[] contentByte = File2Bytes(translateResults.get(0).getFile());
                Bitmap bitmap = BitmapFactory.decodeByteArray(contentByte, 0, contentByte.length);
                ocrResultBitmpa.orinialBitmap = bitmap;
                Bitmap copy = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(copy);  //创建画布
                Paint paint = new Paint();  //画笔
                paint.setStrokeWidth(1);  //设置线宽。单位为像素
                paint.setAntiAlias(true); //抗锯齿
                paint.setColor(Color.WHITE);  //画笔颜色
                paint.setStyle(Paint.Style.FILL);

                canvas.drawBitmap(bitmap,new Matrix(),paint);
                for (TranslateResult translateResult : translateResults) {
                    TranslateResult.TranslationsBean translation = translateResult.getTranslations().get(0);
                    Rect rect = translation.getRect();
                    Bitmap linBg = Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height());
                    Palette.Swatch paletteSwatch = paletteSwatch(linBg);
                    Paint textPaint = new Paint();
                    textPaint.setColor(Color.BLACK);
                    textPaint.setTextSize(10);
                    int start = 0;
                    if(paletteSwatch!=null){
                        paint.setColor(paletteSwatch.getRgb());
                        textPaint.setColor(paletteSwatch.getBodyTextColor());
                    }

                    String content = translation.getText();
                    canvas.drawRect(rect,paint);
                    Rect textBound = new Rect();
                    textPaint.getTextBounds(content, 0, content.length(), textBound);
                    int availableWidth =  rect.width();
                    int availableHeight =  rect.height();
                    int currentWdith = textBound.width();
                    int currentHeight = textBound.height();
                    float cTextSize = textPaint.getTextSize();
                    Log.d("AAA","cTextSize "+cTextSize +"currentWdith "+currentWdith+" - availableWidth "+availableWidth);
                    if(currentWdith<availableWidth){
                        //如果
                        while (availableHeight>currentHeight&&availableWidth>currentWdith){
                            cTextSize = cTextSize+0.5f;
                            textPaint.setTextSize(cTextSize);//这里传入的单位是px
                            textPaint.getTextBounds(content, 0, content.length(), textBound);
                            currentWdith = textBound.width();
                            currentHeight = textBound.height();
                            Log.d("AAA","变大currentWdith "+currentWdith);
                        }


                    }else if(currentWdith>availableWidth){
                        while (currentWdith>availableWidth+cTextSize){
                            cTextSize = cTextSize-0.5f;
                            textPaint.setTextSize(cTextSize);//这里传入的单位是px
                            textPaint.getTextBounds(content, 0, content.length(), textBound);
                            currentWdith = textBound.width();
                            Log.d("AAA","减少currentWdith "+currentWdith);
                        }

                    }
//                    cTextSize = cTextSize+0.5f;
                    if(currentWdith*(2f/3f)<availableWidth){
                        start = (availableWidth - currentWdith )/ 2;
                    }
                    textPaint.setTextSize(cTextSize);
                    Log.d("AAA","cTextSize之后 "+cTextSize);
                    Paint.FontMetricsInt anInt = textPaint.getFontMetricsInt();
                    //字体基线
                    int dy = (anInt.bottom - anInt.top) / 2 - anInt.bottom;
                    canvas.drawText(content, rect.left+start,  dy+rect.top+(rect.bottom-rect.top)/2, textPaint);

                }

                ocrResultBitmpa.translateBitmap = copy;
                return ocrResultBitmpa;
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<OcrResultBitmpa>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("AAA","=== onSubscribe ===");
                    }

                    @Override
                    public void onNext(OcrResultBitmpa ocrResultBitmpa) {
                        msBitmapView.setImageBitmap(ocrResultBitmpa.translateBitmap);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("AAA","=== onError ===" +e);
                    }

                    @Override
                    public void onComplete() {
                        Log.d("AAA","=== onComplete ===");
                    }
                });


    }



    public static byte[] File2Bytes(File file) {
        int byte_size = 1024;
        byte[] b = new byte[byte_size];
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
                    byte_size);
            for (int length; (length = fileInputStream.read(b)) != -1;) {
                outputStream.write(b, 0, length);
            }
            fileInputStream.close();
            outputStream.close();
            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Palette.Swatch paletteSwatch(Bitmap bitmap){
        Palette palette = Palette.from(bitmap).generate();
        try {
            List<Palette.Swatch> swatches = palette.getSwatches();
            if(swatches!=null&&swatches.size()>0){
                Palette.Swatch swatch = swatches.get(0);
                int maxPopulation = swatch.getPopulation();
                int position =0;
                for (int i=0;i<swatches.size();i++){
                    if(maxPopulation<swatches.get(i).getPopulation()){
                        position = i;
                    }
                }
                Log.d("AAA","postio "+position);
                return swatches.get(position);
            }

        }catch (Exception e){

        }

        //获取 靓丽的活力色
        Palette.Swatch  paletteSwatch = palette. getDominantSwatch();
        if(paletteSwatch!=null){
            paletteSwatch =  palette.getVibrantSwatch();
        }

        return paletteSwatch;
    }


    /**
     * 执行
     */
    public void execute(final byte[] content, final MsBitmapView msBitmapView){
        Log.d("AAA","content "+content);
        Observable.create(new ObservableOnSubscribe<MSResultBean>() {
            @Override
            public void subscribe(ObservableEmitter<MSResultBean> emitter) throws Exception {
                RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"),content);

                MultipartBody.Builder multiBuilder=new MultipartBody.Builder();
                multiBuilder.addPart(body);
                multiBuilder.addFormDataPart("language","unk");
                multiBuilder.addFormDataPart("detectOrientation","true");
                RequestBody multiBody=multiBuilder.build();
                Request request = new Request.Builder()
                        .url(URL)
                        .post(multiBody)
                        .addHeader("Content-Type", "application/octet-stream")
                        .addHeader("Ocp-Apim-Subscription-Key", "de418b4320664b1598d05b39af0736c6")
                        .build();
                OkHttpClient httpClient = RetrofitUtil.getHttpClient();
                Response response = httpClient.newCall(request).execute();
                if(response.isSuccessful()){
                    String result = response.body().string();
                    MSResultBean msResultBean = gson.fromJson(result, MSResultBean.class);
                    emitter.onNext(msResultBean);
                }else if(response.code() == 400 ||response.code() == 415 || response.code() == 500){
                    String result = response.body().string();
                    MsOrcException msOrcException = gson.fromJson(result, MsOrcException.class);
                   throw msOrcException;
                }
                emitter.onComplete();
            }
        }).map(new Function<MSResultBean, Bitmap>() {
            @Override
            public Bitmap apply(MSResultBean msResultBean) throws Exception {
                Log.d("AAA","map ");
                Bitmap bitmap = BitmapFactory.decodeByteArray(content, 0, content.length);
                Bitmap copy = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(copy);  //创建画布
                Paint paint = new Paint();  //画笔
                paint.setStrokeWidth(1);  //设置线宽。单位为像素
                paint.setAntiAlias(true); //抗锯齿
                paint.setColor(Color.RED);  //画笔颜色
                paint.setStyle(Paint.Style.STROKE);
                canvas.drawBitmap(bitmap,new Matrix(),paint);
                Region region = msResultBean.getRegions().get(0);
                for (Line line : region.getLines()) {
                    String boundingBox = line.getBoundingBox();
                    String[] split = boundingBox.split(",");
                    RectF rect = new RectF(Float.valueOf(split[0]),Float.valueOf(split[1]),
                            Float.valueOf(split[0])+Float.valueOf(split[2]),Float.valueOf(split[1])+Float.valueOf(split[3]));
                    canvas.drawRect(rect,paint);
                }
                return copy;
            }
        })
                .subscribeOn(Schedulers.io())//执行在io线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        Log.d("AAA","onNext ");
                        msBitmapView.setImageBitmap(bitmap);
                    }

                    @Override
                    public void onError(Throwable e) {
                       Log.d("AAA","e "+e);
                    }

                    @Override
                    public void onComplete() {

                    }
                });


    }
}
